
local meta = FindMetaTable( "Player" );

TestDummyIDs = { }

TestDummyIDs["STEAM_0:1:8387555"] = true;
TestDummyIDs["STEAM_0:1:18008485"] = true;
TestDummyIDs["STEAM_0:1:2512273"] = true;
TestDummyIDs["STEAM_0:0:14498745"] = true;
TestDummyIDs["STEAM_0:0:25902524"] = true;

--This is called once on server join
function meta:Initialize()

	self:GetTable().SendItemNames = { }
	self:GetTable().CLLoadedItems = { }
	self:GetTable().SendPlayerNames = { }
	self:GetTable().Recognized = { }

	self:ApplyMovementSpeeds();
	
	self:GetTable().JumpState = false;
	self:GetTable().JumpStartPos = Vector( 0, 0, 0 );
	
	self:GetTable().IsSprinting = false;
	self:GetTable().NoSprintMode = false;
	
	self:GetTable().NextSprintUpdate = CurTime();
	self:GetTable().RunDegradeAmount = 1;
	
	self:GetTable().CanPickUpItemTime = 0;
	self:GetTable().CanUpdateConsciousBasedSpeed = 0;
	self:GetTable().NextShowSpare = 0;
	
	self:GetTable().ProgressBars = { };
	
	self:GetTable().HeavyWeapon = nil;
	self:GetTable().LightWeapon = nil;
	
	self:GetTable().CanSeePlayerMenu = false;
	
	self:GetTable().CanNextChat = 0;
	
	self:GetTable().IsRagdolled = false;
	self:RemoveRagdoll();
	
	self:GetTable().NextHelp = 0;
	self:GetTable().NextFlashLight = 0;
	self:GetTable().NextPlayerBleed = 0;
	self:GetTable().NextPlayerBleedHeal = 0;
	self:GetTable().NextPlayerBloodHeal = 0;
	self:GetTable().NextPlayerConsciousHeal = 0;
	
	self:GetTable().AttachedProps = { };
	
	self:CreateServerSideVariables();
	
	self:UpdateAdminFlags();
	
	self:Freeze( true );
	
	if( TestDummyIDs[self:SteamID()] ) then
	
		self:CallEvent( "SERR" );
	
	else
	
		if( not GAMEMODE.Debug and not self:IsBot() ) then
		
			local function d()
			
				self:StopMovement();
				self:MakeInvisible( true );
				self:CallEvent( "DoOpenScene" );
				
				timer.Simple( 1, self.sqlOpenSceneSendLoadableCharacters, self );
		
			end
			
			timer.Simple( 2, d );
			
		else
		
			self:CallEvent( "SkipIntro" );
			self:TransferToNewCharacter( "A Debugger", "HECU", 32, "Long black eyes, strong, big black man with an afro", "models/hecu01/1.mdl" );
		
		end
		
	end
	
	self:sqlHandleFirstTimeJoin();

end

--This is called right after the player loads a new character.
function meta:CharacterInitialize()

	-- INVENTORY INITIALIZATION --------------------------------
	self:GetTable().InventoryGrid = { }
	self:GetTable().InventoryList = { }

	for n = 1, MAX_INVENTORIES do
		
		self:GetTable().InventoryGrid[n] = { }
		self:ResetInventory( n );
			
	end
	
	timer.Simple( .5, self.CallEvent, self, "CreateDefaultInventories" );
	self:CreateDefaultInventories();
	-----------------------------------------------------------
	
	if( self:GetTable().HeavyWeapon ) then
	
		self:RemoveHeavyWeapon();
	
	end
	
	if( self:GetTable().LightWeapon ) then
	
		self:RemoveLightWeapon();
	
	end
	
	-- VARIABLE INITIALIZATION 
	self:ResetVariables();
	
	self:FirstTimeSpawnHelp();
	
	self:GetTable().CanSeePlayerMenu = true;
	
end

--Called every think loop
function meta:Think()

	if( not self:Alive() ) then return; end

	self:ProgressBarThink();

	--HOLSTER CODE--
	--To handle weapon changes and what not.
	local weap = self:GetActiveWeapon();
	
	if( weap and weap:IsValid() ) then
	
		if( self:GetPlayerLastHeldWeapon() ~= weap:GetClass() ) then
		
			self:HolsterWeaponIfPossible();
			self:SetPlayerLastHeldWeapon( weap:GetClass() );
		
		end
	
	end
	
	--BLEEDING CODE--
	--Lose blood every 2 seconds
	--Also lowers consciousness
	if( self:GetPlayerBleedingAmount() > 0 ) then
	
		if( CurTime() > self:GetTable().NextPlayerBleed ) then
		
			self:SetPlayerBlood( math.Clamp( self:GetPlayerBlood() - self:GetPlayerBleedingAmount(), 0, 100 ) );
			
			if( self:GetPlayerBlood() < 60 ) then
			
				self:SetPlayerConscious( math.Clamp( self:GetPlayerConscious() - self:GetPlayerBleedingAmount() * 1.9, 0, 100 ) );
			
				if( self:GetPlayerBlood() < 10 ) then
				
					self:GetTable().BledToDeath = true;
					self:TakeHealth( self:GetPlayerBleedingAmount() * 3 );
					self:GetTable().BledToDeath = false;
				
				end
			
			end
			
			self:GetTable().NextPlayerBleed = CurTime() + 2;
			
			self:BleedOutADecal();
		
		end
	
		if( CurTime() > self:GetTable().NextPlayerBleedHeal ) then
		
			self:SetPlayerBleedingAmount( math.Clamp( self:GetPlayerBleedingAmount() - .05, 0, 100 ) );
			self:GetTable().NextPlayerBleedHeal = CurTime() + 18;
		
		end
	
	else
	
		if( self:GetPlayerBlood() < 100 ) then
		
			if( CurTime() > self:GetTable().NextPlayerBloodHeal ) then
			
				self:SetPlayerBlood( math.Clamp( self:GetPlayerBlood() + .25, 0, 100 ) );
				self:GetTable().NextPlayerBloodHeal = CurTime() + 20;
			
			end
		
		end
		
		if( self:GetPlayerConscious() < 100 ) then
		
			if( CurTime() > self:GetTable().NextPlayerConsciousHeal ) then
			
				self:SetPlayerConscious( math.Clamp( self:GetPlayerConscious() + .15, 0, 100 ) );
				self:GetTable().NextPlayerConsciousHeal = CurTime() + 20;
			
			end			
		
		end
	
	end

	--JUMP CODE--
	--This code is used to monitor jump distance and calls our HandleJumpFall function when the player lands.
	if( not self:GetTable().JumpState ) then

		if( not self:OnGround() ) then
		
			self:GetTable().JumpState = true;
			self:GetTable().JumpStartPos = self:GetPos();
		
		end
		
	else
	
		if( self:OnGround() ) then
		
			self:GetTable().JumpState = false;
			local dist = self:GetPos().z - self:GetTable().JumpStartPos.z;
			
			if( dist < 0 ) then
			
				self:HandleJumpFall( math.abs( dist ) );
			
			end
			
		end
		
	end
	
	--JOGGING CODE--
	--This code creates a differentiation between jogging and sprinting.
	-- Sprinting is when both the walk key and the sprint key are pressed.
	if( self:KeyDown( IN_SPEED ) and self:KeyDown( IN_WALK ) ) then
	
		if( not self:GetTable().IsSprinting ) then
		
			self:SetRunSpeed( self:GetTable().SprintSpeed or 400 );
			self:GetTable().IsSprinting = true;
		
		end
	
	else
	
		if( self:GetTable().IsSprinting ) then
			
			if( self:GetTable().NoSprintMode ) then
			
				self:NoSprintMovement();
			
			else
			
				self:ApplyMovementSpeeds();
				
			end
			
			self:GetTable().IsSprinting = false;
	
		end
		
	end
	
	--Handles sprint meter
	if( self:GetTable().NextSprintUpdate < CurTime() ) then
	
		self:GetTable().NextSprintUpdate = CurTime() + .2;
		local sprint = self:GetPlayerSprint();
	
		if( self:GetVelocity():Length() > 10 ) then
		
			if( self:KeyDown( IN_SPEED ) ) then
				
				if( self:KeyDown( IN_WALK ) ) then
					
					sprint = sprint - self:GetTable().RunDegradeAmount;
					
				else
					
					sprint = sprint - self:GetTable().RunDegradeAmount * .4;
					
				end
					
				if( sprint <= 0 and not self:GetTable().NoSprintMode ) then
				
					self:NoSprintMovement();
					self:GetTable().NoSprintMode = true;
				
				elseif( self:GetTable().NoSprintMode ) then
				
					--Don't apply normal movement speeds until after sprint gets back up to 15`
					if( sprint > 15 ) then
				
						self:ApplyMovementSpeeds();
						self:GetTable().NoSprintMode = false;
					
					end
					
				end
				
			else
				
				sprint = sprint + .05;
				
			end
				
		else
			
			sprint = sprint + .1;
			
		end

		self:SetPlayerSprint( math.Clamp( sprint, 0, 100 ) );

	end

end

